home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / InetAddress.java < prev    next >
Text File  |  1998-09-22  |  18KB  |  535 lines

  1. /*
  2.  * @(#)InetAddress.java    1.46 98/07/27
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.net;
  16.  
  17. import java.util.Hashtable;
  18.  
  19. /**
  20.  * This class represents an Internet Protocol (IP) address. 
  21.  * <p>
  22.  * Applications should use the methods <code>getLocalHost</code>, 
  23.  * <code>getByName</code>, or <code>getAllByName</code> to 
  24.  * create a new <code>InetAddress</code> instance. 
  25.  *
  26.  * @author  Chris Warth
  27.  * @version 1.46, 07/27/98
  28.  * @see     java.net.InetAddress#getAllByName(java.lang.String)
  29.  * @see     java.net.InetAddress#getByName(java.lang.String)
  30.  * @see     java.net.InetAddress#getLocalHost()
  31.  * @since   JDK1.0
  32.  */
  33. public final 
  34. class InetAddress implements java.io.Serializable {
  35.     String hostName;
  36.     int address;    // Currently we only deal effectively with 32-bit addresses. 
  37.             // However this field can be expanded to be a byte array 
  38.             // or a 64-bit quantity without too much effort.
  39.     int family;
  40.  
  41.     /** use serialVersionUID from JDK 1.0.2 for interoperability */
  42.     private static final long serialVersionUID = 3286316764910316507L;
  43.  
  44.     /*
  45.      * Load net library into runtime.
  46.      */
  47.     static {
  48.     System.loadLibrary("net");
  49.     }
  50.  
  51.     /** 
  52.      * Constructor for the Socket.accept() method.
  53.      * This creates an empty InetAddress, which is filled in by
  54.      * the accept() method.  This InetAddress, however, is not
  55.      * put in the address cache, since it is not created by name.
  56.      */
  57.     InetAddress() {
  58.       family = impl.getInetFamily();
  59.     }
  60.  
  61.     /**
  62.      * Creates an InetAddress with the specified host name and IP address.
  63.      * @param hostName the specified host name
  64.      * @param addr the specified IP address.  The address is expected in 
  65.      *          network byte order.
  66.      * @exception UnknownHostException If the address is unknown.
  67.      */
  68.     InetAddress(String hostName, byte addr[]) {
  69.     this.hostName = new String(hostName);
  70.     this.family = impl.getInetFamily();
  71.     /*
  72.      * We must be careful here to maintain the network byte
  73.      * order of the address.  As it comes in, the most
  74.      * significant byte of the address is in addr[0].  It
  75.      * actually doesn't matter what order they end up in the
  76.      * array, as long as it is documented and consistent.
  77.      */
  78.     address  = addr[3] & 0xFF;
  79.     address |= ((addr[2] << 8) & 0xFF00);
  80.     address |= ((addr[1] << 16) & 0xFF0000);
  81.     address |= ((addr[0] << 24) & 0xFF000000);
  82.     }
  83.  
  84.     /**
  85.      * Utility routine to check if the InetAddress is a 
  86.      * IP multicast address. IP multicast address is a Class D
  87.      * address i.e first four bits of the address are 1110.
  88.      * @since   JDK1.1
  89.      */
  90.     public boolean isMulticastAddress() {
  91.     return ((address & 0xf0000000) == 0xe0000000);
  92.     }
  93.  
  94.     /**
  95.      * Returns the fully qualified host name for this address.
  96.      * If the host is equal to null, then this address refers to any
  97.      * of the local machine's available network addresses.
  98.      *
  99.      * @return  the fully qualified host name for this address.
  100.      * @since   JDK1.0
  101.      */
  102.     public String getHostName() {
  103.     if (hostName == null) {
  104.         try {
  105.         hostName = new String(impl.getHostByAddr(address));
  106.         InetAddress[] arr = (InetAddress[])addressCache.get(hostName);
  107.         if(arr != null) {
  108.             for(int i = 0; i < arr.length; i++) {
  109.             if(hostName.equalsIgnoreCase(arr[i].hostName) && 
  110.                address != arr[i].address) {
  111.                 /* This means someone's playing funny games with DNS
  112.                  * This hostName used to have one IP address, now it 
  113.                  * has another.  At any rate, don't let them "see" 
  114.                  * the new hostName, and don't cache it either.
  115.                  */
  116.                 hostName = getHostAddress();
  117.                 break;
  118.             }
  119.             }
  120.         } else { 
  121.             /* hostname wasn't in cache before.  It's a real hostname,
  122.              * not "%d.%d.%d.%d" so cache it
  123.              */
  124.             arr = new InetAddress[1];
  125.             arr[0] = this;
  126.             addressCache.put(hostName, arr);
  127.         }
  128.         /* finally check to see if calling code is allowed to know
  129.          * the hostname for this IP address, ie, connect to the host
  130.          */
  131.         SecurityManager sec = System.getSecurityManager();
  132.         if (sec != null && !sec.getInCheck()) {
  133.             sec.checkConnect(hostName, -1);
  134.         }
  135.         } catch (SecurityException e) {
  136.         hostName = getHostAddress();
  137.         } catch (UnknownHostException e) {
  138.         hostName = getHostAddress();
  139.         }
  140.     }
  141.     return hostName;
  142.     }
  143.  
  144.     /**
  145.      * Returns the raw IP address of this <code>InetAddress</code> 
  146.      * object. The result is in network byte order: the highest order 
  147.      * byte of the address is in <code>getAddress()[0]</code>. 
  148.      *
  149.      * @return  the raw IP address of this object.
  150.      * @since   JDK1.0
  151.      */
  152.     public byte[] getAddress() {    
  153.     byte[] addr = new byte[4];
  154.  
  155.     addr[0] = (byte) ((address >>> 24) & 0xFF);
  156.     addr[1] = (byte) ((address >>> 16) & 0xFF);
  157.     addr[2] = (byte) ((address >>> 8) & 0xFF);
  158.     addr[3] = (byte) (address & 0xFF);
  159.     return addr;
  160.     }
  161.  
  162.     /**
  163.      * Returns the IP address string "%d.%d.%d.%d"
  164.      * @return raw IP address in a string format
  165.      * @since   JDK1.1
  166.      */
  167.     public String getHostAddress() {    
  168.          return ((address >>> 24) & 0xFF) + "." +
  169.                 ((address >>> 16) & 0xFF) + "." +
  170.                 ((address >>>  8) & 0xFF) + "." +
  171.                 ((address >>>  0) & 0xFF);
  172.      }
  173.  
  174.  
  175.     /**
  176.      * Returns a hashcode for this IP address.
  177.      *
  178.      * @return  a hash code value for this IP address. 
  179.      * @since   JDK1.0
  180.      */
  181.     public int hashCode() {
  182.     return address;
  183.     }
  184.  
  185.     /**
  186.      * Compares this object against the specified object.
  187.      * The result is <code>true</code> if and only if the argument is 
  188.      * not <code>null</code> and it represents the same IP address as 
  189.      * this object. 
  190.      * <p>
  191.      * Two instances of <code>InetAddress</code> represent the same IP 
  192.      * address if the length of the byte arrays returned by 
  193.      * <code>getAddress</code> is the same for both, and each of the 
  194.      * array components is the same for the byte arrays. 
  195.      *
  196.      * @param   obj   the object to compare against.
  197.      * @return  <code>true</code> if the objects are the same;
  198.      *          <code>false</code> otherwise.
  199.      * @see     java.net.InetAddress#getAddress()
  200.      * @since   JDK1.0
  201.      */
  202.     public boolean equals(Object obj) {
  203.     return (obj != null) && (obj instanceof InetAddress) &&
  204.         (((InetAddress)obj).address == address);
  205.     }
  206.  
  207.     /**
  208.      * Converts this IP address to a <code>String</code>.
  209.      *
  210.      * @return  a string representation of this IP address.
  211.      * @since   JDK1.0
  212.      */
  213.     public String toString() {
  214.     return getHostName() + "/" + getHostAddress();
  215.     }
  216.  
  217.     /* 
  218.      * Cached addresses - our own litle nis, not! 
  219.      *
  220.      * Do not purge cache of numerical IP addresses, since 
  221.      * duplicate dynamic DNS name lookups can leave the system
  222.      * vulnerable to hostname spoofing attacks.  Once a hostname
  223.      * has been looked up in DNS and entered into the Java cache, 
  224.      * from then on, the hostname is translated to IP address only
  225.      * via the cache.
  226.      */
  227.     static Hashtable        addressCache = new Hashtable();
  228.     static InetAddress        unknownAddress;
  229.     static InetAddress        anyLocalAddress;
  230.     static InetAddress      localHost;
  231.     static InetAddress[]    unknown_array; // put THIS in cache
  232.     static InetAddressImpl  impl;
  233.  
  234.     /* 
  235.      * generic localHost to give back to applets 
  236.      * - private so not API delta
  237.      */
  238.     private static InetAddress      loopbackHost;
  239.  
  240.     static {
  241.  
  242.     /*
  243.      * Property "impl.prefix" will be prepended to the classname of the
  244.      * implementation object we instantiate, to which we delegate the real work 
  245.      * (like native methods).  This property can vary across implementations
  246.      * of the java.* classes.  The default is an empty String "".
  247.      */
  248.  
  249.     String prefix = System.getProperty("impl.prefix", "");
  250.     try {
  251.         impl = null;
  252.         impl = (InetAddressImpl)(Class.forName("java.net." + prefix + "InetAddressImpl")
  253.                            .newInstance());
  254.     } catch (ClassNotFoundException e) {
  255.         System.err.println("Class not found: java.net." + prefix + 
  256.                    "InetAddressImpl:\ncheck impl.prefix property " +
  257.                    "in your properties file.");
  258.     } catch (InstantiationException e) {
  259.         System.err.println("Could not instantiate: java.net." + prefix + 
  260.                    "InetAddressImpl:\ncheck impl.prefix property " +
  261.                    "in your properties file.");
  262.     } catch (IllegalAccessException e) {
  263.         System.err.println("Cannot access class: java.net." + prefix + 
  264.                    "InetAddressImpl:\ncheck impl.prefix property " +
  265.                    "in your properties file.");
  266.     }
  267.  
  268.     if (impl == null) {
  269.         try {
  270.         impl = (InetAddressImpl)(Class.forName("java.net.InetAddressImpl")
  271.                      .newInstance());
  272.         } catch (Exception e) {
  273.         throw new Error("System property impl.prefix incorrect");
  274.         }
  275.     }
  276.  
  277.     unknownAddress = new InetAddress();
  278.     anyLocalAddress = new InetAddress();
  279.     impl.makeAnyLocalAddress(anyLocalAddress);
  280.     byte[] IP = new byte[4];
  281.     IP[0] = 0x7F;
  282.     IP[1] = 0x00;
  283.     IP[2] = 0x00;
  284.     IP[3] = 0x01;
  285.     loopbackHost = new InetAddress("localhost", IP);
  286.  
  287.     /* find the local host name */
  288.     try {
  289.         localHost = new InetAddress();
  290.         localHost.hostName = impl.getLocalHostName();
  291.         /* we explicitly leave the address of the local host
  292.          * uninitialized.  A DNS lookup in this, the static
  293.          * initializer, will cause a machine disconnected
  294.          * from the network to hang - it'll be trying to query
  295.          * a DNS server that isn't there.
  296.          *
  297.          * Instead, we just get the hostname of the local host.
  298.          * The native code for this just calls gethostname()
  299.          * which should be pretty innocuous - it shouldn't try
  300.          * to contact a DNS server.  If any application
  301.          * calls InetAddress.getLocalHost(), we initialize
  302.          * the local host's address there if not already initialized.
  303.          *
  304.          * Note that for this to work it is also essential that
  305.          * the localHost InetAddress is _NOT_ put into the address cache
  306.          * here in the static initializer (which happens if we call
  307.          * getByName() from the static initializer).  It _IS_ OK
  308.          * to put it in the addressCache after initialization.
  309.          *
  310.          * The unitialized state of the localHost's address is -1,
  311.          * or IP address 255.255.255.255 which we know cannot be
  312.          * a legal host address.
  313.          */
  314.         localHost.address = -1;
  315.     } catch (Exception ex) { /* this shouldn't happen */
  316.         localHost = unknownAddress;
  317.     }
  318.  
  319.     /* cache the name/address pair "0.0.0.0"/0.0.0.0 */
  320.     String unknownByAddr = new String("0.0.0.0");
  321.     unknown_array = new InetAddress[1];
  322.     unknown_array[0] = new InetAddress(unknownByAddr, unknownAddress.getAddress());
  323.     addressCache.put(unknownByAddr, unknown_array);
  324.     }
  325.  
  326.     /**
  327.      * Determines the IP address of a host, given the host's name. The 
  328.      * host name can either be a machine name, such as 
  329.      * "<code>java.sun.com</code>", or a string representing its IP 
  330.      * address, such as "<code>206.26.48.100</code>". 
  331.      *
  332.      * @param      host   the specified host, or <code>null</code> for the
  333.      *                    local host.
  334.      * @return     an IP address for the given host name.
  335.      * @exception  UnknownHostException  if no IP address for the
  336.      *               <code>host</code> could be found.
  337.      * @since      JDK1.0
  338.      */
  339.     public static InetAddress getByName(String host)
  340.     throws UnknownHostException {
  341.     Object obj = null;
  342.     if (host == null || host.length() == 0) {
  343.         return loopbackHost;
  344.     }
  345.  
  346.         if (!Character.isDigit(host.charAt(0))) {
  347.         return getAllByName0(host)[0];
  348.     } else {
  349.         /* The string (probably) represents a numerical IP address.
  350.          * Parse it into an int, don't do uneeded reverese lookup,
  351.          * leave hostName null, don't cache.  If it isn't an IP address,
  352.          * (i.e., not "%d.%d.%d.%d") or if any element > 0xFF, 
  353.          * we treat it as a hostname, and lookup that way.
  354.          * This seems to be 100% compliant to the RFC1123 spec: 
  355.          * a partial hostname like 3com.domain4 is technically valid.
  356.          */
  357.  
  358.         int IP = 0x00;
  359.         int hitDots = 0;
  360.         char[] data = host.toCharArray();
  361.  
  362.         for(int i = 0; i < data.length; i++) {
  363.         char c = data[i];
  364.         if (c < 48 || c > 57) { // !digit
  365.             return getAllByName0(host)[0];
  366.         }
  367.         int b = 0x00;
  368.         while(c != '.') {
  369.             if (c < 48 || c > 57) { // !digit
  370.             return getAllByName0(host)[0];
  371.             }
  372.             b = b*10 + c - '0';
  373.  
  374.             if (++i >= data.length)
  375.             break;
  376.             c = data[i];
  377.         }
  378.         if(b > 0xFF) { /* bogus - bigger than a byte */
  379.             return getAllByName0(host)[0];
  380.         }
  381.         IP = (IP << 8) + b;
  382.         hitDots++;
  383.         }
  384.  
  385.         if(hitDots != 4 || host.endsWith(".")) {
  386.         return getAllByName0(host)[0];
  387.         }
  388.  
  389.         InetAddress in = new InetAddress();
  390.         in.address = IP;
  391.         in.hostName = null;
  392.         return in;
  393.     }
  394.  
  395.     }
  396.  
  397.     /** 
  398.      * Determines all the IP addresses of a host, given the host's name. 
  399.      * The host name can either be a machine name, such as 
  400.      * "<code>java.sun.com</code>", or a string representing 
  401.      * its IP address, such as "<code>206.26.48.100</code>". 
  402.      *
  403.      * @param      host   the name of the host.
  404.      * @return     an array of all the IP addresses for a given host name.
  405.      * @exception  UnknownHostException  if no IP address for the
  406.      *               <code>host</code> could be found.
  407.      * @since      JDK1.0
  408.      */
  409.     public static InetAddress getAllByName(String host)[]
  410.     throws UnknownHostException {
  411.  
  412.     if (host == null || host.length() == 0) {
  413.         throw new UnknownHostException("empty string");
  414.     }
  415.  
  416.     if(Character.isDigit(host.charAt(0))) {
  417.         InetAddress[] ret = new InetAddress[1];
  418.         ret[0] = getByName(host);
  419.         return ret;
  420.     } else {
  421.         return getAllByName0(host);
  422.     }
  423.     }
  424.  
  425.     private static InetAddress[] getAllByName0 (String host) 
  426.     throws UnknownHostException  {
  427.     /* If it gets here it is presumed to be a hostname */
  428.     /* Cache.get can return: null, unknownAddress, or InetAddress[] */
  429.         Object obj = null;
  430.     Object objcopy = null;
  431.  
  432.     /* make sure the connection to the host is allowed, before we
  433.      * give out a hostname
  434.      */
  435.     SecurityManager security = System.getSecurityManager();
  436.     if (security != null && !security.getInCheck()) {
  437.         security.checkConnect(host, -1);
  438.     }
  439.  
  440.     synchronized (addressCache) {
  441.         obj = addressCache.get(host);
  442.  
  443.     /* If no entry in cache, then do the host lookup */
  444.     
  445.         if (obj == null) {
  446.         try {
  447.             /*
  448.              * Do not put the call to lookup() inside the
  449.              * constructor.  if you do you will still be
  450.              * allocating space when the lookup fails.
  451.              */
  452.             byte[][] byte_array = impl.lookupAllHostAddr(host);
  453.             InetAddress[] addr_array = new InetAddress[byte_array.length];
  454.  
  455.             for (int i = 0; i < byte_array.length; i++) {
  456.             byte addr[] = byte_array[i];
  457.             addr_array[i] = new InetAddress(host, addr);
  458.             }
  459.             obj = addr_array;
  460.         } catch (UnknownHostException e) {
  461.             obj  = unknown_array;
  462.         }
  463.         if (obj != unknown_array)
  464.             addressCache.put(host, obj);
  465.         }
  466.     } /* end synchronized block */
  467.  
  468.     if (obj == unknown_array) {
  469.         /*
  470.          * We currently cache the fact that a host is unknown.
  471.          */
  472.         throw new UnknownHostException(host);
  473.     }
  474.  
  475.     /* Make a copy of the InetAddress array */
  476.     try {
  477.           objcopy = ((InetAddress [])obj).clone();
  478.           // the following line is a hack, to ensure that the code
  479.           // can compile for both the broken compiler and the fixed one.
  480.           if (objcopy == null) 
  481.           throw new CloneNotSupportedException();
  482.     } catch (CloneNotSupportedException cnse) {
  483.           cnse.printStackTrace();
  484.     }
  485.  
  486.     return (InetAddress [])objcopy;
  487.     }
  488.  
  489.     /**
  490.      * Returns the local host.
  491.      *
  492.      * @return     the IP address of the local host.
  493.      * @exception  UnknownHostException  if no IP address for the
  494.      *               <code>host</code> could be found.
  495.      * @since      JDK1.0
  496.      */
  497.     public static InetAddress getLocalHost() throws UnknownHostException {
  498.         if (localHost.equals(unknownAddress)) {
  499.         throw new UnknownHostException();
  500.     }
  501.  
  502.     try {
  503.         /* If the localhost's address is not initialized yet, initialize
  504.          * it.  It is no longer initialized in the static initializer 
  505.          * (see comment there).
  506.          */
  507.  
  508.         if (localHost.address == -1) {
  509.         localHost = getAllByName(localHost.hostName)[0];
  510.         /* This puts it in the address cache as well */
  511.         }
  512.  
  513.             /* make sure the connection to the host is allowed: if yes,
  514.          * return the "real" localHost; if not, return loopback "127.0.0.1"
  515.          */
  516.         SecurityManager security = System.getSecurityManager();
  517.         if (security != null && !security.getInCheck()) 
  518.         security.checkConnect(localHost.getHostName(), -1);
  519.         return localHost;
  520.  
  521.     } catch (java.lang.SecurityException e) {
  522.         return loopbackHost;
  523.     }
  524.     }
  525. }
  526.  
  527. class InetAddressImpl {
  528.     native String getLocalHostName() throws UnknownHostException;
  529.     native void makeAnyLocalAddress(InetAddress addr);
  530.     native byte[][]
  531.         lookupAllHostAddr(String hostname) throws UnknownHostException;
  532.     native String getHostByAddr(int addr) throws UnknownHostException;
  533.     native int getInetFamily();
  534. }
  535.